<script setup lang="ts">
import { Map, View } from 'ol'
import { computed, nextTick, onBeforeUnmount, onMounted, reactive, ref, useAttrs, watch } from 'vue'
import { getLastPosition, useGetEnclosureDataApi, useGetTrackPosApi } from '@/api/gps/gps'
import sourceVector from 'ol/source/Vector'
import Feature from 'ol/Feature'
import layerVector from 'ol/layer/Vector'
import SourceVector from 'ol/source/Vector'
import { Circle, Fill, Stroke, Style, Icon, Text } from 'ol/style'
import { Polygon, Point, Circle as gCircle, LineString } from 'ol/geom'
import start_IconPng from '@/assets/gps/start_icon.png'
import end_IconPng from '@/assets/car/end_icon.png'
import car_bluePng from '@/assets/car/car_blue.png'
import stopCar from '@/assets/gps/stop_icon.png'
import { ElMessage, ElCard, ElButton, ElProgress, ElInputNumber, ElDatePicker, ElLoading, ElDialog } from 'element-plus'
import { IsPtInPoly } from '@/utils/gps/inside'
import { createLayers2, createMap } from '@/utils/ol/maptools'
import { wsg2mapcoor } from '@/utils/gps/maptransform'
import { useMineApi } from '@/api/biz/mine'
import pos_icon from '@/assets/gps/pos_icon.png'
import { fenceDecode } from '@/utils/gps/fence'
import { createLayer2, createLayer3, createPointLayer } from '@/utils/gps/drawEnclosure'
import moment from 'moment'

const ctx = useAttrs()
const visible = ref(true)

let demo: any = null
const loading = ref(false)
// const dateRange = ref<any>(props.time)
const record = reactive<{ position: any[]; travelPath: any[]; stopPosition: any[] }>({
  position: [],
  travelPath: [],
  stopPosition: []
})
let trackTimer: any = null
const openMap = ref<Map>()
const vectorLayer = ref<layerVector<any>>()
const iconLayer = ref()
const carSource = ref()
let source: SourceVector = new SourceVector()
// 围栏数据
const fenceData = ref()
let linePath: any
let carFeature: Feature
// 播放速率
const playSpeed = ref(100)
// 进度
const percentage = ref(0)
const currentPosition = ref<{ [key: string]: any }>()
const polylinePath = ref([])
let stepInterval: any = null
const currentStep = ref(0)
const isPlay = ref(false)
const speed = ref(0)
// watch(()=> props.time, (value) =>{
//     dateRange.value = value
// })

watch(
  () => loading.value,
  (value) => {
    if (value) {
      nextTick(() => {
        demo = ElLoading.service({
          target: '.demo',
          text: '生成数据中...',
          background: 'rgba(255,255,255,0.7)'
        })
      })
    } else {
      demo?.close()
    }
  },
  {
    immediate: true
  }
)
const currentPage = computed(() => {
  return (record.position.length > 0 ? currentStep.value + 1 : 0) + ' / ' + record.position.length
})

onBeforeUnmount(() => {
  if (trackTimer) {
    clearInterval(trackTimer)
  }
  clearInterval(stepInterval)
})
function init() {
  const { lng, lat } = wsg2mapcoor(31.503466, 104.78875)
  nextTick(() => {
    initMap([lng, lat])
    // getData()
    loading.value = false
  })
}

onMounted(() => {
  openMap.value = createMap('map-fence-s', createLayers2())
})

/**
 * 重置数据
 */
function handleReset() {
  record.position = []
}
/**
 * 获取数据
 */
function setTrackData(imei: string, mineId: number, data: any) {
  loading.value = true
  useMineApi(mineId).then((res) => {
    fenceData.value = res.data
    initEnclosure()
    init()
  })
  let startTime, endTime
  let isReal = false
  if (data.status) {
    if (data.status < 3) {
      startTime = data.planningTime
      endTime = moment().format('YYYY-MM-DD HH:mm:ss')
      isReal = true
    } else {
      startTime = data.startTime
      endTime = data.endTime
    }
  } else {
    startTime = data.planningTime
    endTime = moment().format('YYYY-MM-DD HH:mm:ss')
  }
  useGetTrackPosApi({
    imei: imei,
    startTime,
    endTime,
    withPos: true,
    withStop: true,
    withTrip: false
  })
    .then(
      (res) => {
        const { positions, stops } = res.data
        record.position = positions
        if (stops?.length) {
          record.stopPosition = stops.map((item: any) => {
            const { lng, lat } = wsg2mapcoor(item.longitude, item.latitude)
            return {
              lng,
              lat,
              time: timeFormat(item.duration)
            }
          })
        }
        if (positions?.length) {
          currentPosition.value = positions[positions.length - 1]
          record.travelPath = positions.map((item: any) => {
            const { lng, lat } = wsg2mapcoor(item.longitude, item.latitude)
            return [lng, lat]
          })
          if (vectorLayer.value) openMap.value?.removeLayer(vectorLayer.value)
          if (iconLayer.value) openMap.value?.removeLayer(iconLayer.value)
          trajectoryPath(record.travelPath)
        } else {
        }
      },
      (error) => {
        ElMessage.error('数据异常，如有疑问请联系管理员')
      }
    )
    .finally(() => {
      loading.value = false
      if (isReal) {
        trackTimer = setInterval(() => getTheLatest(imei), 5000)
      }
    })
}
let time = 0

/**
 * 获取过去5秒的位置
 * @param imei
 */
function getTheLatest(imei) {
  getLastPosition({
    imeis: imei,
    lastQueryPositionTime: time
  })
    .then((res) => {
      const data: any = res.data
      if (!data.length) return
      data.forEach((item) => {
        const { lng, lat } = wsg2mapcoor(item.longitude, item.latitude)
        record.travelPath.push([lng, lat])
        record.position.push(item)
      })
      currentPosition.value = data[0]
      if (vectorLayer.value) openMap.value?.removeLayer(vectorLayer.value)
      if (iconLayer.value) openMap.value?.removeLayer(iconLayer.value)
      trajectoryPath(record.travelPath, data[0].direction)
    })
    .finally(() => {
      time = getTimer()
    })
}
function getTimer() {
  const d = new Date()
  return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds())
}

/**
 * 初始化围栏
 */
function initEnclosure() {
  if (fenceData.value.latitude && fenceData.value.longitude) {
    let minePos = wsg2mapcoor(fenceData.value.longitude, fenceData.value.latitude)
    openMap.value?.addLayer(createPointLayer(minePos.lng, minePos.lat, pos_icon))
  }
  if (fenceData.value.fenceStart) {
    const area: any = fenceDecode(fenceData.value.fenceStart)
    let gpsPath: any = []
    area.path.map((e: any) => {
      gpsPath.push([e.lng, e.lat])
    })
    openMap.value?.addLayer(createLayer2(gpsPath, true))
  }
  if (fenceData.value.fenceStart2) {
    const area: any = fenceDecode(fenceData.value.fenceStart2)
    let gpsPath: any = []
    area.path.map((e: any) => {
      gpsPath.push([e.lng, e.lat])
    })
    openMap.value?.addLayer(createLayer2(gpsPath, true))
  }
  if (fenceData.value.fenceEnd) {
    const area: any = fenceDecode(fenceData.value.fenceEnd)
    let gpsPath: any = []
    area.path.map((e: any) => {
      gpsPath.push([e.lng, e.lat])
    })
    openMap.value?.addLayer(createLayer2(gpsPath, false))
  }
  if (fenceData.value.fenceEnd2) {
    const area: any = fenceDecode(fenceData.value.fenceEnd2)
    let gpsPath: any = []
    area.path.map((e: any) => {
      gpsPath.push([e.lng, e.lat])
    })
    openMap.value?.addLayer(createLayer2(gpsPath, false))
  }
  if (fenceData.value.line) {
    const area: any = fenceDecode(fenceData.value.line)
    let gpsPath: any = []
    area.path.map((e: any) => {
      gpsPath.push([e.lng, e.lat])
    })
    openMap.value?.addLayer(createLayer3(gpsPath))
  }
}

/**
 * 日期转换
 * @param timeLong
 */
function timeFormat(timeLong: number) {
  const timeStamp = Math.floor(timeLong / 1000)
  const days = Math.floor(timeStamp / (24 * 3600))
  const yu = timeStamp % (24 * 3600)
  const hours = Math.floor(yu / 3600)
  const yu2 = yu % 3600
  const minutes = Math.floor(yu2 / 60)
  const seconds = yu2 % 60
  return (days === 0 ? '' : days + '天') + (hours === 0 ? '' : hours + '小时') + (minutes === 0 ? '' : minutes + '分') + (seconds === 0 ? '-' : seconds + '秒')
}

/**
 * 初始化地图
 * @param options
 */
function initMap(options: number[]) {
  initEnclosure()
  openMap.value?.getView().animate({
    center: [fenceData.value.longitude, fenceData.value.latitude],
    duration: 500,
    zoom: 12
  })
}

/**
 * 画轨迹
 * @param e
 * @param direction
 */
function trajectoryPath(e: any[], direction = 0) {
  const polyline = e
  // 实例化图层
  let geometry = new LineString(polyline)
  let source = new sourceVector()
  // 绘制轨迹
  let LineFeature = new Feature(geometry)
  source.addFeature(LineFeature)
  vectorLayer.value = new layerVector({
    source,
    style: new Style({
      fill: new Fill({
        color: 'rgba(255, 255, 255, 0.6)'
      }),
      stroke: new Stroke({
        color: 'rgba(0,153,255, 0.6)',
        width: 8
      }),
      image: new Circle({
        radius: 7,
        fill: new Fill({
          color: '#0099FF'
        })
      })
    })
  })
  openMap.value?.addLayer(vectorLayer.value)
  setMark(polyline, direction)
}

/**
 * 画Marker点
 * @param e
 * @param direction
 */
function setMark(e: any[], direction = 0) {
  let markers: any[] = [
    {
      po: e[0],
      key: start_IconPng,
      name: 'start'
    }
    // {
    //   po: e[e.length - 1],
    //   key: end_IconPng,
    //   name: 'end',
    // },
  ]
  if (record.stopPosition.length > 0) {
    markers.push(
      ...record.stopPosition.map((item: any) => {
        return {
          po: [item.lng, item.lat],
          key: stopCar,
          name: 'stop',
          time: item.time
        }
      })
    )
  }
  let isIcon: any[] = []
  markers.forEach((item: any) => {
    // 创建图标特性
    let iconFeature = new Feature({
      geometry: new Point(item.po),
      name: item.name
    })
    // 创建图标样式
    iconFeature.setStyle(
      new Style({
        image: new Icon({
          // 定义图标锚点
          anchor: [12, 0.5],
          anchorOrigin: 'bottom-left',
          anchorXUnits: 'pixels',
          anchorYUnits: 'pixels',
          src: item.key
        }),
        text:
          item.name === 'stop'
            ? new Text({
                font: '13px sans-serif',
                offsetX: 0,
                offsetY: -50,
                textAlign: 'center',
                textBaseline: 'middle',
                text: `停留时间：${item.time}`,
                backgroundFill: new Fill({
                  color: 'rgba(128,134,149, 0.8)'
                }),
                fill: new Fill({
                  color: '#fff'
                }),
                padding: [4, 5, 4, 5]
              })
            : undefined
      })
    )
    isIcon.push(iconFeature)
  })
  let vectorSource = new sourceVector({
    features: isIcon
  })
  // 图标添加进矢量容器
  carSource.value = vectorSource
  // 创建矢量图层
  iconLayer.value = new layerVector({
    source: vectorSource
  })
  openMap.value?.addLayer(iconLayer.value)
  // 绘制车表
  timeMarker([record.position[record.position.length - 1].longitude, record.position[record.position.length - 1].latitude], direction, false)
  // 定位地图总心
  openMap.value?.getView().setCenter(e[0])
  isInside(currentPosition.value?.latitude, currentPosition.value?.longitude)
}

/**
 * 画车
 * @param v
 * @param rotation
 * @param status
 */
function timeMarker(v: any[], rotation: number, status: boolean) {
  if (status) carSource.value.removeFeature(carFeature)
  const { lng, lat } = wsg2mapcoor(v[0], v[1])
  carFeature = new Feature({
    geometry: new Point([lng, lat])
  })
  carFeature.setStyle(
    new Style({
      image: new Icon({
        // 定义图标锚点
        anchor: [10, 18],
        anchorOrigin: 'bottom-left',
        anchorXUnits: 'pixels',
        anchorYUnits: 'pixels',
        rotation: (Math.PI / 180) * (rotation % 360),
        src: car_bluePng
      })
    })
  )
  carSource.value.addFeature(carFeature)
}

/**
 * 判断小车是否在可视范围内
 * @param lat
 * @param lng
 */
function isInside(lat: number, lng: number) {
  let isArr: any = openMap.value?.getView().calculateExtent(openMap.value?.getSize())
  if (
    !IsPtInPoly(lat, lng, [
      { longitude: isArr[2], latitude: isArr[1] },
      { longitude: isArr[0], latitude: isArr[1] },
      { longitude: isArr[0], latitude: isArr[3] },
      { longitude: isArr[2], latitude: isArr[3] }
    ])
  )
    openMap.value?.getView().setCenter([lng, lat])
}

/**
 * 开始播放
 */
function handlePlay() {
  if (record.position.length === 0) return ElMessage.warning('无法播放')
  stepInterval = setInterval(() => {
    if (currentStep.value < record.position.length - 1) {
      isPlay.value = true
      currentStep.value++
      currentPosition.value = record.position[currentStep.value]
      timeMarker([currentPosition.value?.longitude, currentPosition.value?.latitude], currentPosition.value?.course, true)
      isInside(currentPosition.value?.latitude, currentPosition.value?.longitude)
      speed.value = record.position[currentStep.value].speed
      percentage.value = parseFloat(((currentStep.value / record.position.length) * 100).toFixed(1))
    } else {
      percentage.value = 100
      handlePause()
    }
  }, playSpeed.value)
}

/**
 * 暂停播放
 */
function handlePause() {
  isPlay.value = false
  clearInterval(stepInterval)
}

/**
 * 重置播放
 */
function handleRefresh() {
  currentStep.value = 0
  percentage.value = 0
  currentPosition.value = record.position[0]
  polylinePath.value.splice(0, polylinePath.value.length)
}

/**
 * 上一步
 */
function handlePrev() {
  if (currentStep.value > 0 && currentStep.value <= record.position.length) currentStep.value--
  polylinePath.value.splice(currentStep.value, polylinePath.value.length)
  adjust()
}

/**
 * 下一步
 */
function handleNext() {
  if (currentStep.value < record.position.length) currentStep.value++
  adjust()
}
function adjust() {
  const start = record.position[currentStep.value]
  currentPosition.value = start
  // 获取速度表
  speed.value = start?.speed
  // 获取百分比
  percentage.value = parseFloat(((currentStep.value / record.position.length) * 100).toFixed(1))
  const rotation = start?.course
  timeMarker([start.longitude, start.latitude], rotation, true)
}

defineExpose({
  setTrackData
})
</script>

<template>
  <div style="height: 100%">
    <div id="map-fence-s" class="map-fence"></div>
  </div>
</template>

<style scoped lang="scss">
.map-fence {
  height: 100%;
}
</style>
